#!/bin/sh
## pnp modules bootloader v0.16
## (c) Denis Kaganovich, under Anarchy license
## consume preprocessed /lib/modules/$KV/modules.alias

[[ -z "$TMPDIR" ]] && [[ -e /temp ]] && TMPDIR="/temp"

## millisecons
#SYS_FIND="/sys"
SYS_FIND=/sys/devices

export blkid_cache="/etc/blkid.sh.cache"

pids=""

single(){
	grep -qF ">$1<" "${PNP_TMP}.$2" && return 1
	echo ">$1<" >>"${PNP_TMP}.$2"
	return 0
}

mod(){
	local m m1 m2
	for m in "${@}" ; do
		while [ -z "${m##-}" ]; do
			m="${m%%-*}_${m#*-}"
		done
		[[ -e "/sys/module/$m" ]] && continue # fast
		$CHK "$m" 0 || continue
		modalias "$m" || {
			echo ">$m<" >>"${PNP_TMP}".4
			continue
		}
		case $PARALLEL in
		no|0) ;;
		2)
			m2=""
			for m1 in $ALIAS ; do
				modparam $m1
				$INSMOD
				[[ -e "$m1" ]] &&
				m2="$m2 insmod "$m1" $PARAM ;" ||
				pnpass=1
			done
			$cmd_quiet || echo -ne "\033[0G\033[0K$LCOUNT	[...] $m1 $PARAM"
			eval "( ${m2%;} ) >/dev/null 2>&1 &"
			pids="$pids$! "
			continue
		;;
		*)
			pids="$pids$pid "
			pid=""
		;;
		esac
		for m1 in $ALIAS ; do
#			m="${m1##*/}"
#			[[ -e "/sys/module/${m%.ko}" ]] && continue
			modparam $m1
			$INSMOD
			[[ -e "$m1" ]] || {
				pnpass=1
				continue
			}
			wait $pid
			$cmd_quiet || echo -ne "\033[0G\033[0K$LCOUNT	$m1 $PARAM"
			insmod "$m1" $PARAM >/dev/null 2>&1 &
			pid="$!"
		done
	done
}

refresh(){
	LCOUNT="${LCOUNT}."
	echo -ne "\033[0G\033[0K$LCOUNT"
	local i j l

	wait $pid $pids
	pid=""
	pids=""

	${cmd_fast:=false} && return 1

	sed -e 's%^\([^ 	]*\)[	 ]*.*$%>\1<%g' </proc/modules >"${PNP_TMP}".1
	cat `grep -ls "^DRIVER=" $(find $SYS_FIND -name uevent -print 2>/dev/null) </dev/null` </dev/null |grep "^DRIVER=\|^MODALIAS="|sed -e 's%-%_%g' -e 's%^.*=\(.*\)$%>\1<%g' >>"${PNP_TMP}".1
	if [[ "$(cat ${PNP_TMP}.1 $checks)" == "$(cat ${PNP_TMP}.2)" ]] ; then
		cat "${PNP_TMP}".3 "${PNP_TMP}".4 >"${PNP_TMP}".0
		if grep -q "[/]sbin/mdev" /proc/*/cmdline; then
			REFRESH_SAME=''
			[[ "$1" == "n" ]] && REFRESH_SAME=1
			return 0
		fi
		[[ "$REFRESH_SAME$1" == "n" ]] || return 1
		return 0
	fi
	sort -u "${PNP_TMP}".1 >"${PNP_TMP}".0
	if ! $cmd_quiet ; then
		echo -ne "\033[0G\033[0K${BOLD}   ::${NORMAL}Loaded:"
		for i in $(sort -m ${PNP_TMP}.0 ${PNP_TMP}.3 | uniq -u) ; do
			[[ "$1" == "n" ]] && echo "$i" >>/nopnp.lst
			i="${i#>}"
			i="${i%<}"
			[[ -e "/sys/module/$i" ]] && echo -ne " $i"
		done
		echo ""
	elif $cmd_unload && [[ "$1" == "n" ]] ; then
		sort -m ${PNP_TMP}.0 ${PNP_TMP}.3 | uniq -u >>/nopnp.lst
	fi
	cat "${PNP_TMP}".1 $checks >"${PNP_TMP}".2
	cp "${PNP_TMP}".0 "${PNP_TMP}".3
	cat "${PNP_TMP}".4 >>"${PNP_TMP}".0
	REFRESH_SAME=''
	[[ "$1" == "n" ]] && REFRESH_SAME=1
	return 0
}

count(){
	[[ "${LCOUNT#????????????????}" == "${LCOUNT}" ]] && return 0
	bad_msg "Deadloop?"
	return 1
}

mnt_loop(){
	local i
	if losetup $1 $2; then
		for i in 0 1 1 1 1 1; do
			mount -o ro,$cmd_loopflags $1 $3 2>/dev/null && return 0
			sleep $i
		done
		mount -o ro,$cmd_loopflags $1 $3 && return 0
		losetup -d $1
		return 1
	fi
	mount -o loop,ro,$cmd_loopflags $2 $3
	return $?
}

root_fsck_rw(){
	! [[ -w $NEW_ROOT ]] && {
		/sbin/fsck -C0 -T -p $NEW_ROOT
		case $? in
		0|1)mount -o remount,rw $NEW_ROOT;;
		2|3)sync;echo b >/proc/sysrq-trigger;;
		esac
	}
}

upcase(){
	echo "$*"|tr a-z A-Z
	return $?
}

mod_unload(){
	local h i="$NEW_ROOT/lib/modules/$KV" l="$NEW_ROOT/usr/src/linux-$KV" m="" x y yy r=$NEW_ROOT/mnt/ram
	cd /
	echo "$SAVE_HOTPLUG" >/proc/sys/kernel/hotplug
	${cmd_fsck:-false} && root_fsck_rw
	if grep -q "^[^ ]* $NEW_ROOT squashfs" /proc/mounts; then
		echo -ne "(squashfs)"
		mkdir -p /etc/mnt
		cp -a $NEW_ROOT/mnt/* /etc/mnt
		mount -t ramfs none $NEW_ROOT/mnt -o rw,noatime,nodiratime && cp -a /etc/mnt/* $NEW_ROOT/mnt
		[[ -e /etc/resolv.conf ]] && {
			sort -u /etc/resolv.conf >$r/etc/resolv.conf
			h="${NFSROOT:-$REAL_ROOT}"
			x="${h##//}"
			x="${x%%[:/]*}"
			read y </proc/sys/kernel/domainname
			y="${y#(none)}"
			[[ -n "$y" ]] && [[ "$x" != "$h" ]] && {
				echo "(server=$x domain=$y)"
				sed -i \
				-e "s:dc1\.domain\.local:$x:g" \
				-e "s:domain\.local:$y:g" \
				-e "s:=domain:=${y%%.*}:g" \
				-e "s:=local:=${y#*.}:g" \
				$r/etc/* $r/etc/*/* 2>/dev/null
				y=`upcase "$y"` && sed -i \
				-e "s:DC1\.DOMAIN\.LOCAL:$(upcase $x):g" \
				-e "s:DOMAIN\.LOCAL:$y:g" \
				-e "s:= DOMAIN:= ${y%%.*}:g" \
				$r/etc/* $r/etc/*/* 2>/dev/null
			}
		}
		# /mnt/ram/ram.lst: <dir>[/] [<mode>]
		while read x y; do
			if [[ -z "$y" ]]; then
				mkdir -p $r${x%/*}
				cp -a $NEW_ROOT$x $r$x
			else
				mkdir -p $r$x
				chmod $y $r$x
			fi
			[[ -n "${x##*/}" ]] && mount --bind $r$x $NEW_ROOT$x
		done <$r/ram.lst
	fi
	if [[ -L $i/kernel ]] && i=`ls $l.*fs 2>/dev/null` && [[ -f "$i" ]]; then
		echo -ne "(mount $i)"
		mnt_loop /dev/loop3 "$i" $l
	elif ! [[ -e $i ]] ; then
		if ${cmd_autoinstall:-false} ; then
			echo -ne "(Installing /lib/modules/$KV)"
			mount -o remount,rw ${NEW_ROOT} &&
			cp -a /lib/modules/$KV $i
		else
			echo -ne '(use "autoinstall" to install modules)'
		fi
	fi
#	for i in /rd /lib; do
#		[[ -d "$i" ]] && umount $i && break
#	done
	umount /lib/modules /lib/firmware /rd /lib 2>/dev/null
	losetup -d /dev/loop1 >/dev/null 2>&1
	l=""
	$cmd_unload && [[ -n "$REAL_ROOT" ]] && [[ -e "/nopnp.lst" ]] || return
	echo -n "(removing unlocked modules"
	while read i; do
		i="${i#>}"
		l="${i%<} $l"
	done </nopnp.lst
	i="$(cat /proc/modules)"
	while [[ "$i" != "$m" ]]; do
		m="$i"
		echo -n "."
		rmmod $l >/dev/null 2>&1
		i="$(cat /proc/modules)"
	done
	echo -n ")"
}

pnp_options(){
	PARALLEL=0
	cmd_nofb=false
	cmd_nopnp=false
	cmd_unload=false
	cmd_noraid=false
	cmd_real_init=/sbin/init
	local i v m p= d="${TMPDIR}/modparam"
	mkdir $d
	for i in "${@}" ; do
	case "$i" in
	parallel-startup) PARALLEL=1 ;;
	parallel-startup=*) PARALLEL="${i#*=}" ;;
	moduleparam=*)
		i="${i#*=}"
		p="*/${i%%:*}.ko)PARAM=\"${i#*:}\";;$p"
	;;
	md=*)	v="cmd_${i%%=*}"
		eval "$v=\"\$$v ${i#*=}\""
	;;
	*=*)	v="${i%%=*}"
		case "$v" in
		*.*) echo "${i#*.}" >"$d/${v%%/*}";;
		*) export cmd_`echo "$v"|sed -e 's:[^a-zA-Z0-9_]:_:g'`="${i#*=}" ;;
		esac
	;;
	*.*) echo "${i#*.}" >"$d/${i%%/*}";;
	scandelay) cmd_scandelay=10 ;;
	*) export cmd_`echo "$i"|sed -e 's:[^a-zA-Z0-9_]:_:g'`=true ;;
	esac
	done
	v=
	for i in $(ls -1 "$d"); do
		m="${i%%.*}"
		[[ -z "$m" ]] && continue
		i="$(cat "$d/$i")"
		[[ -z "$i" ]] && MDOLIST="$MDOLIST $m"
		[[ "$v" == "$m" ]] && {
			p="$p $i"
			continue
		}
		[[ -n "$v" ]] && p="$p';;"
		p="$p*/$m.ko)PARAM='$i"
		v="$m"
	done
	[[ -n "$v" ]] && p="$p';;"
	rm "$d" -Rf
	$cmd_nofb && p="*/fb.ko|*/drm_kms_helper.ko)INSMOD=continue;;$p"
	[[ -n "$cmd_noload" ]] && p="*/$(echo "$cmd_noload"|sed -e 's/,/.ko|*\//g').ko)INSMOD=continue;;$p"
	echo "modparam(){
INSMOD=
case \"\$1\" in
1)INSMOD=\${REORDER:-continue};;
$p
*)PARAM='';;
esac
}" >/etc/modparam.sh
	$cmd_quiet && good_msg(){ return; }
}

link_dir(){
	local i
	for i in "$1"/*; do
		i="${i#$1}"
		if [[ -L "$1$i" ]] && ( [[ -L "$2$i" ]] || ! [[ -e "$2$i" ]] ) ; then
			cp "$1$i" "$2$i" -a
		elif [[ -d "$2$i" ]]; then
			if [[ -L "$2$i" ]]; then
				local d="$(readlink "$2$i")"
				rm "$2$i"
				mkdir "$2$i"
				link_dir "$d" "$2$i"
			fi
			link_dir "$1$i" "$2$i"
		elif [[ "$i" != "/*" ]]; then
			ln -sf "$1$i" "$2$i"
		fi
	done
}

pnp_init(){
	eval "pnp_options $(cat /proc/cmdline)" # parsing
	local l
	read SAVE_HOTPLUG </proc/sys/kernel/hotplug
	for l in /*.loopfs; do
	if [[ -f "$l" ]]; then
		for i in `find /lib -name "*.ko"` ; do
			insmod $i
		done
		local d="${l%.loopfs}"
		mkdir $d 2>/dev/null
		mnt_loop /dev/loop1 $l $d
		break
	fi
	done
	[[ -d /rd ]] && link_dir /rd
	[[ -d /lib/root ]] && link_dir /lib/root

	[[ -e /lib/modules/$KV/modules.dep ]] && return
	# pnponly
	rm /sbin/modprobe
}

override_modprobe(){
loadsh modprobe || return
local f="/sbin/modprobe"
[[ -e $f ]] && ! ( grep -q "bug #197730" $f && rm /sbin/modprobe ) && return
ln -s /etc/modprobe.sh $f
echo $f >/proc/sys/kernel/modprobe
}

wild(){
	grep "$1" <modules.other|grep -v "${2:-x--}"|sed -e 's:.*/::g' -e 's/\...$//g'
}

cpufreq(){
	[[ -n "$freq" ]] && return
	local l="" CHK=true c="" ok=""
	for i in $(wild $@) ; do
		[[ -n "$c" ]] && rmmod $c >/dev/null 2>&1
		mod $i
		c="$i"
		wait $pid $pids
		pid=""
		pids=""
		for i in `grep -ls "$c" $(find /sys/devices/system/cpu -name scaling_driver)` ; do
			read i2 <"${i%scaling_driver}cpuinfo_transition_latency" || continue
			[[ "$i2" -gt "${l:=${i2}}" ]] && continue
			if [[ "$i2" == "$l" ]] ; then
				[[ "${freq#*${c} }" == "$freq" ]] && freq="$freq$c "
			else
				freq=" $c "
				l="$i2"
			fi
			ok="$c"
			break
		done 2>/dev/null </dev/null
	done
	[[ -z "$ok" ]] && return
	[[ "$ok" != "$c" ]] && rmmod $c >/dev/null 2>&1
	[[ "$freq" != "$c" ]] && mod $freq
}

cpufreq_gov(){
	local gov1=""
	for i1 in $gov ; do
		mod cpufreq_${i1}
		wait $pid $pids
		pid=""
		pids=""
		for i in `find /sys/devices/system/cpu -name scaling_governor` ; do
			echo $i1 >"$i" || gov1="$gov1 $i1"
#			[[ "$(cat "$i")" == "$i1" ]] || gov1="$gov1 $i"
		done 2>/dev/null
		rmmod cpufreq_${i1} >/dev/null 2>&1
		[[ -z "$gov1" ]] && break
	done
}

empty_hwopts(){
	local i
	[[ -e /etc/modules ]] && for i in $* ; do
		 echo -ne "" >/etc/modules/$i
	done
}

# params: part loop net?
# out: $DETECTED_LOOPS++, $DETECTED_ROOTS++
detect_part(){
	grep -qF ">$*<" "${PNP_TMP}.5" && return 0
	local l o=ro,$cmd_real_rootflags
	wait $pid $pids
	pid=""
	pids=""
	$cmd_quiet || echo -ne "\033[0G\033[0K$LCOUNT	Inspecting: $1"
	mkdir /DETECT_ROOT || return 1
	[[ -n "$3" ]] && {
		o="$o,nolock,rsize=1024,wsize=1024"
		case "$3:$1" in
		cifs:*|auto://*)o="$o,user=,guest -t cifs";;
		auto:*|nfs:*)o="$o -t nfs";;
		*)o="$o,user=,guest -t $3";;
		esac
	}
	mount -o $o "$1" /DETECT_ROOT >/dev/null 2>&1 || {
		rmdir /DETECT_ROOT
		return 1
	}
	echo ">$*<" >>"${PNP_TMP}.5"
	[[ "${2:-false}" != false ]] && for l in $( {
		if [[ "$2" == true ]]; then
			fstype ${LOOPS_}
		else
			fstype /DETECT_ROOT/$2
		fi
		} |sed -e 's%^\(.*:\).* TYPE="\([^"]*\)".*$%\1\2%g'
	    ) ; do
		DETECTED_LOOPS="$DETECTED_LOOPS $1:${l#/DETECT_ROOT/}"
		l="${l#*:}"
		case "$l" in
		ext2) LOOPTYPE=normal ;;
		*) LOOPTYPE="$l" ;;
		esac
		mod $l # loop
	done
	[[ -e "/DETECT_ROOT/$cmd_real_init" ]] && grep -sq "^$1[ 	]*/[ 	]" /DETECT_ROOT/etc/mtab && DETECTED_ROOTS="$DETECTED_ROOTS $1"
#	[[ -e "/DETECT_ROOT/$cmd_real_init" ]] && DETECTED_ROOTS="$DETECTED_ROOTS $1"
	umount /DETECT_ROOT >/dev/null 2>&1
	rmdir /DETECT_ROOT
}

part_(){
	[[ -b "$1" ]] && echo "$*" && return
	( blkid $1 || blkid -t "$1" ) | sed -e 's:^.* TYPE="swap".*$::g' -e 's/:.*$//g'
}

detect_root(){
	local i d="${cmd_detect_root:-false}" l="$cmd_loop" fs
	[[ "$d" == true ]] && d=""
	if [[ "$d" != false ]]; then
		# if real_root & loop hard-defined - don't probe other loops
		[[ -n "$REAL_ROOT" ]] && [[ "${l:-true}" != true ]] && l=false
		# if real_root & loop hard-defined - probe all loops
#		[[ -n "$REAL_ROOT" ]] && [[ "${l:-true}" != true ]] && l=true
		for i in `part_ "$d"`; do
			case "$i" in
			/dev/loop1) ;;
			*) detect_part "$i" "$l" ;;
			esac
		done
	fi
	if [[ -n "$REAL_ROOT" ]] && [[ "${cmd_loop:-false}" != false ]]; then
		detect_part "$(part_ "$REAL_ROOT")" "$cmd_loop"
	fi
	[[ -n "$NFSROOT" ]] && [[ -n "`ifconfig`" ]] && {
		detect_part "$NFSROOT" "$cmd_loop" "${NFSLIKE_FS:-auto}"
	}
}

# autoconfig works only with built-in card?
ip_config(){
local ip dev s d h
[[ -n "`ifconfig`" ]] && {
	[[ -z "$NFSROOT" ]] && {
		NFSROOT="$(dhcp_get rootserver):$(dhcp_get rootpath)"
		[[ "$NFSROOT" == : ]] && NFSROOT=
	}
	return
}
for ip in "${@}"; do
    msg_ "Configuring IP $ip"
    eval "set `echo "'$ip'"|sed -e "s/:/' '/g"` ''"
    for dev in ${6:-$(ls -1 /sys/class/net/ 2>/dev/null|grep -v "^lo$")}; do
	d=
	case "$7" in
	on|any|dhcp)
		mod af_packet
		msg_
		busybox udhcpc -i $dev -n -T 15 -q || continue
		d=`grep -s "^domain " /etc/resolv.conf|sed -e 's:^domain ::'`
		[ -e /rootpath ] && NFSROOT=`cat /rootpath`
	;;
	esac
	[[ -n "$1$4" ]] && ifconfig $dev $1 ${4:+netmask $4}
	i="${5%%.*}"
	[[ -n "$i" ]] && echo "$i" >/proc/sys/kernel/hostname
	[[ "$i" != "$5" ]] && d="${5#*.}"
	[[ -n "$d" ]] && for d in $d; do
		echo "search $d" >>/etc/resolv.conf
		echo "$d" >/proc/sys/kernel/domainname
	done
	[[ -n "$3" ]] && route add default gw $3 dev $dev
	case "$NFSLIKE_FS" in
	cifs)i="//$2/";;
	*)i="$2:";;
	esac
	NFSROOT="${2:+$s}$cmd_nfsroot"
	break
    done
done
[[ ${cmd_telnetd:-false} != false ]] && [[ -n "`ifconfig`" ]] && telnetd ${cmd_telnetd#true}
}

dhcp_get(){
	local i r=''
	for i in `busybox dmesg | grep rootserver | sed -e "s/,/ /g"`; do
		if [[ "`echo $i | sed -e "s/=/ /g" | cut -d " " -f 1`" == "$1" ]]; then
			r="`echo "$i" | sed -e "s/=/ /g" | cut -d " " -f 2`"
			# FIXME: first value will be more balanced, but last - actual in longrun
			break
		fi
	done
	echo -ne "$r"
}

# modifyed genkernel's function to support other network filesystems (/dev/<filsystem>)
findnfsmount() {
	( [[ -z "$NFSLIKE_FS" ]] && [[ -n "$NFSROOT" ]] ) ||
	    grep -q "[ 	]${NFSLIKE_FS:=nfs}\$" /proc/filesystems || return 1
	ip_config ::::::dhcp
	if [[ -n "`ifconfig`" ]]; then
		if [[ -z "$NFSROOT" ]]; then
			bad_msg "The DHCP Server did not send a valid root-path."
			bad_msg "Please check your DHCP setup, or provide a nfsroot=<...> parameter."
		else
			local o="ro,nolock,rsize=1024,wsize=1024,$cmd_real_rootflags" m="$NEW_ROOT" unc
			[[ "$CDROOT" != '0' ]] && m="$m/mnt/cdrom"
			case "$NFSLIKE_FS:$NFSROOT" in
			cifs:*|://*)o="$o,user=,guest,serverino";NFSLIKE_FS=cifs;;
			:*|nfs:*)NFSLIKE_FS=nfs;;
			*)o="$o,user=,guest $o,user= $o";;
			esac
			grep -q "[ 	]${NFSLIKE_FS:=nfs}\$" /proc/filesystems || return 1
			for o in $o; do
			    for unc in '' "$(echo ",unc=$NFSROOT"|sed -e 's:/:\\:g')"; do # try new cifs
				good_msg "Attempting to mount $NFSLIKE_FS on $NFSROOT into $m -o $o"
				if mount -t $NFSLIKE_FS "$NFSROOT" $m -o "$o$unc" ; then
					# FIXME: Need to start portmap and the other rpc daemons in
					# order to remount rw.
					REAL_ROOT="/dev/nfs"
					REAL_ROOTFLAGS="$o"
					return 0
				fi
				[[ "$NFSLIKE_FS" == nfs ]] && break
			    done
			done
			bad_msg "$NFSLIKE_FS Mounting failed. Is the path correct ?"
		fi
	fi
	return 1
}

msg_(){
	wait $pid $pids
	pid=""
	pids=""
	if $cmd_quiet; then
		echo -ne "\033[0G"
	else
		echo -ne "\033[0G\033[0K"
		[[ -n "$*" ]] && good_msg "$*"
	fi
}

fstype(){
	blkid "${@}" 2>/dev/null || blkid -t "${@}" 2>/dev/null || echo "${@}"
}

resume(){
	local i
	[[ -e /sys/power/resume ]] || return
	[[ -n "$*" ]] && for i in "${@}"; do
		[[ "$i" == true ]] && {
			cat $(grep -l "[1-9]" /sys/class/block/*/size|grep -v /loop|sed -e 's:size$:dev:') >/sys/power/resume
			continue
		}
		i="${i#/dev/}"
		for i in "/sys/class/block/$i/" `grep -ls "^DEVNAME=$i$" /sys/class/block/*/uevent`; do
			cat "${i%uevent}dev" >/sys/power/resume
		done
	done 2>/dev/null </dev/null
	echo "0:0" >/sys/power/resume 2>/dev/null
}

detect_fs(){
	local i m="" md="$USE_MDADM" dm="$USE_DMRAID_NORMAL" t="$cmd_detect_root" lvm="$USE_LVM_NORMAL" evms="$USE_EVMS_NORMAL" mddef=true
	[[ -n "$NFSLIKE_FS" ]] && [[ "$REAL_ROOT" == /dev/nfs ]] && REAL_ROOT="/dev/$NFSLIKE_FS"
	case "$t" in
	true|false)t="";
	esac
	if $waitscan; then
		[[ -e /etc/modules/waitscan ]] || mod scsi_wait_scan
		empty_hwopts waitscan
		[[ -n "$cmd_scandelay" ]] && sleep "$cmd_scandelay"
		waitscan=false
		wait $pid $pids
		pid=""
		pids=""
		rmmod scsi_wait_scan 2>/dev/null
		[[ -n "$cmd_elevator" ]] && for i in /sys/class/block/*/queue/scheduler; do # embed
			echo "$cmd_elevator" >$i
		done
		/sbin/mdev -s block
	fi
	resume "$cmd_resume"
	# dmraid/lvm/evms unsure
	for i in $( {
			fstype $t
			[[ -n "$REAL_ROOT" ]] && ( [[ -n "$t" ]] || ! [[ -b "$REAL_ROOT" ]] ) && [[ "$REAL_ROOT" != "$t" ]] && fstype $REAL_ROOT
	    } 2>/dev/null | sed -e 's%^\(/dev/[^ ]*\):.* TYPE="swsuspend".*$%0susp:\1%' -e 's:^.* TYPE="\([^"]*\)".*$:\1:g'| sort -u ); do
		case $i in
		/dev/md*)
			[[ -x /sbin/mdadm ]] || mknod "$i" b 9 "${i#/dev/md}"
			md=1
		;;
		linux_raid_member|mdraid) md=1 ;; # use right blkid
		/dev/mapper*|/dev/dm*) dm=1 ;;
		EVMS*|evms*)
			evms=1
			dm=1
		;;
		LVM*|lvm*)
			lvm=1
			dm=1
		;;
		*raid*)
			m="$m $(wild "/$i/\|raid") $i"
			dm=1
		;;
		/dev/*)
			[[ "$REAL_ROOT" == "$i" ]] && REAL_ROOT=/dev/nfs # compat
			i="${i#/dev/}"
			m="$m $i"
			NFSLIKE_FS="$i"
		;;
		swap) ;;
		0susp:*)[[ -z "$cmd_resume" ]] && resume "${i#0susp:}";;
		*) m="$m $(wild "/$i/") $i" ;;
		esac
	done
	[[ -n "$dm" ]] && m="$m dm-mod"
	# FIXME: IMHO it will be loaded after dmraid failure
#	[[ -n "$dm" ]] && m=$m $(wild "/md/dm-\|raid_class")"
	mod $(for i in $m;do echo "$i";done|sort -u)
	if [[ -n "$evms" ]]; then
		msg_ "Activating EVMS"
		if evms_activate ; then
			USE_EVMS_NORMAL_=""
			lvm=""
			USE_LVM_NORMAL=""
			USE_LVM_NORMAL_=""
		fi
	fi
	if [[ -n "$lvm" ]]; then
		msg_ "Activating LVM"
		if vgscan --ignorelockingfailure --mknodes 2>/dev/null ; then
			sleep 2
			vgchange -ay --ignorelockingfailure 2>/dev/null
			USE_LVM_NORMAL_=""
			evms=""
			USE_EVMS_NORMAL=""
			USE_EVMS_NORMAL_=""
		fi
	fi
	for i in $cmd_md ; do
		set `echo "$i"|sed -e 's:,: :g'` ""
		i="$1$2$3$4"
		if [[ -n "$5" ]] && [[ "${i##*/dev/}" == "$i" ]]; then
			mod "raid$2"
			i="$1 --level=$2 --chunk=$3"
			shift 4
			i="--build /dev/md$i"
		else
			mod $(wild "/md/raid")
			i="$1"
			shift
			[[ "${i#d}" != "$i" ]] && i="${i#d} --run"
			i="--assemble /dev/md$i"
		fi
		msg_
		/sbin/mdadm $i --raid-devices=$# $*
	done
	if [[ -n "$md$dm" ]]; then
		# maybe dm wrong here, but try
		if [[ -e '/etc/mdadm.conf' ]]; then
			mod `( grep " level=" /etc/mdadm.conf || ( /sbin/mdadm --examine --scan -v|grep " level=" ) ) | sed -e 's:^.* level=\([^ ]*\) .*$:\1:g' | sort -u`
		else
			mddef=false
			[[ -n "$t" ]] && echo "DEVICE $t" >/etc/mdadm.conf
			/sbin/mdadm --examine --scan -v >/etc/mdadm.conf.all
			mod `grep " level=" /etc/mdadm.conf.all | sed -e 's:^.* level=\([^ ]*\) .*$:\1:g' | sort -u`
			cp /etc/mdadm.conf.all /etc/mdadm.conf
			if [[ "$cmd_detect_root" != true ]] && [[ -n "$USE_MDADM" ]]; then
				# do not assemble other raids
				local a=""
				while read i; do
					if [[ "${i#ARRAY $REAL_ROOT }" != "$i" ]] || [[ "${i#ARRAY $cmd_detect_root }" != "$i" ]]; then
						a=1
					elif [[ "${i#ARRAY }" != "$i" ]]; then
						a=""
					else
						i=" $i"
					fi
					[[ -n "$a" ]] && echo "$i"
				done </etc/mdadm.conf.all >/etc/mdadm.conf
			fi
		fi
		if ! $cmd_noraid && ( [[ -n "$md" ]] || grep -q ARRAY /etc/mdadm.conf ); then
			msg_
			# busybox | mdadm | all raid modules; raidautorun - wrong
			/sbin/mdadm --assemble || /sbin/mdadm --assemble --scan ||
			    ( mod $(wild "/md/") ; ( /sbin/mdadm --assemble || /sbin/mdadm --assemble --scan || ( [[ -n "$cmd_part$REAL_ROOT" ]] && mdstart $cmd_part $REAL_ROOT ) || raidautorun $REAL_ROOT ) ) &&
			    USE_MDADM_=""
		fi
		$mddef || rm /etc/mdadm.conf
	fi
	if [[ -n "$dm" ]]; then
		mod $(dmraid -r --sep " " -cf,r,t $t 2>/dev/null)
		if ! $cmd_noraid; then
			msg_ "Activating Device-Mapper RAID(s)"
			dmraid -ay ${DMRAID_OPTS} || {
				mod $(wild "/md/\|raid")
				msg_
				dmraid -ay ${DMRAID_OPTS}
			} && USE_DMRAID_NORMAL_=""
		fi
	fi
	resume "$cmd_resume"
	detect_root
	return 0
}

gentoo_compat_hwopts(){
	local i i1
	for i1 in ${MY_HWOPTS} ; do
		if [[ -e "/etc/modules/$i1" ]] ; then
			for i in `cat /etc/modules/$i1` ; do
				grep -q "^$i\$" "modules.pnp" || mod "$i"
			done
		else
			mod $(wild "/${i1}[./]")
		fi
	done
}

load_hand_made(){
	## some hand-made autoloads
#	$cmd_nofb || [[ -z "$(cat /proc/fb 2>/dev/null)" ]] || mod fbcon
	mod $(cd /etc/modflags && cat $(ls -1 /sys/module) </dev/null 2>/dev/null)
	grep -sq yeah /proc/sys/net/ipv4/tcp_available_congestion_control &&
		echo yeah >/proc/sys/net/ipv4/tcp_congestion_control
	[[ -e /dev/freefall ]] && [[ -x /bin/hpfall ]] && /bin/hpfall /dev/sda
}

load_hand_made0(){
	## some hand-made autoloads, stage0
	local f=`echo $(grep "^vendor_id\|^flags" /proc/cpuinfo|sort -u)`
	mod $MDOLIST ${cmd_elevator:+${cmd_elevator}_iosched} $(cd /etc/modflags && cat $(cat /sys/bus/acpi/devices/*/path|sed -e 's:^\\::') $f $(ls -1 /sys/module) </dev/null 2>/dev/null)
	wait $pid
	pid=""
	pids=""
	# frost. save your silicon (and power): autoload best cpufreq driver
	freq=`cat $(find /sys/devices/system/cpu -name scaling_driver 2>/dev/null) </dev/null`
	case "$f" in
	*\ lm\ *AuthenticAMD*)
		[[ -e /lib/firmware/amd-ucode/microcode_amd.bin ]] && mod microcode
		cpufreq powernow-k8
		: ${gov:=conservative ondemand}
	;;
	*AuthenticAMD*)
		cpufreq cpufreq-nforce2
		cpufreq powernow
	;;
	esac
	cpufreq cpufreq "drivers/cpufreq/\|powernow\|nforce2"
	[[ -z "$freq" ]] && return
	${cmd_nopowersave:-false} && return
	[[ -z "$gov" ]] && if grep -sq 1 /sys/class/power_supply/BAT*/present && ! grep -sq 1 /sys/class/power_supply/AC*/online ; then
		gov="conservative ondemand"
	else
		gov="ondemand conservative"
	fi
	cpufreq_gov
	rmmod freq_table >/dev/null 2>&1
	for i in /sys/devices/system/cpu/sched_*_power_savings ; do
		[[ -e "$i" ]] && echo 2 >$i 2>/dev/null
	done
}

load_misc(){
	# do: loadall[=...] or process MY_HWOPTS
	for i in $cmd_loadall ; do
		[[ "$i" == 'true' ]] && i=''
		i1="${i%%:*}"
		i2="${i#*:}"
		[[ -z "$i1" ]] && i1=".*"
		# default: exclude slow probe, fatal to unload, etc
		[[ "$i2" == "$i" ]] && i2='/tcrypt.ko\|/paride/\|/media/\|/sound/\|/microcode\.\|/isdn/\|/net/\|/video/'
		mod $(wild "$i1" "$i2")
	done
	[[ -z "$cmd_loadall" ]] && [[ "$NODETECT" != '1' ]] && gentoo_compat_hwopts # deprecated
	ip_config $cmd_ip
	detect_fs
}

set_root_loop(){
	set 1 `echo "$1"|sed -e 's/:/ /g'`
	REAL_ROOT="$2"
	LOOP="$3"
	LOOPTYPE="$4"
}

# vs. "find" optimization [dis]order
ordered_modalias(){
	local i
	if [[ -e "$1/modalias" ]]; then
		! grep -sq "^DRIVER=." "$1/uevent" && mod "`cat "$1/modalias"`"
#	elif [[ -e "$1/uevent" ]]; then
#		i=`grep -s "^MODALIAS=" "$1/uevent"` && mod "${i#MODALIAS=}"
	fi
	for i in "$1"/* ; do
		[[ -d "$i" ]] && [[ ! -L "$i" ]] && ordered_modalias "$i"
	done
}

fast_modalias(){
	# ssb (b43) have no modalias
	mod $MDOLIST `grep -sh "^MODALIAS=" $(find $SYS_FIND -name uevent -print) </dev/null|sed -e 's:^MODALIAS=::g' -e 's:[ -]:_:g'|sort -u`
}

ofast_modalias(){
	mod `grep -sh "^MODALIAS=" $(find $SYS_FIND -name uevent -print|sort) </dev/null|sed -e 's:^MODALIAS=::g' -e 's:[ -]:_:g'|uniq`
}

etc_modalias(){
	[[ -f /etc/modalias ]] && mv /etc/modalias /etc/modalias_ || return 1
	mod `cat /etc/modalias_`
	rm /etc/modalias_
	return $pnpass
}

loadsh(){
	[[ "${SHLOADED##* $1 }" == "${SHLOADED}" ]] &&
		[[ -e /etc/$1.sh ]] && . /etc/$1.sh && SHLOADED="$SHLOADED $1 "
	return $?
}

mntnewroot(){
	if mkdir "$NEW_ROOT" 2>/dev/null ; then
		if [[ -z "$NFSLIKE_FS" ]] || ! findnfsmount; then
			mount -t "${cmd_rootfstype:-auto}" -o ro,$cmd_real_rootflags "$REAL_ROOT" "$NEW_ROOT" || rmdir "$NEW_ROOT"
		fi
		[[ "$NEW_ROOT" == /dev/nfs ]] && [[ -e /newroot ]] && NEW_ROOT="/newroot"
		if [[ -e "$NEW_ROOT" ]] && [[ -n "$LOOP" ]]; then
			LOOP_ROOT=
#			LOOP_ROOT="$NEW_ROOT"
			for i in mnt/livecd; do
				[[ -d $NEW_ROOT/$i ]] && LOOP_ROOT="$NEW_ROOT/$i" && break
			done
			[[ -z "$LOOP_ROOT" ]] && mkdir ${LOOP_ROOT:=/newroot.loop}
			if ! ( [[ -d "$LOOP_ROOT" ]] && mnt_loop /dev/loop0 "/newroot/$LOOP" "$LOOP_ROOT" && [[ -e "$LOOP_ROOT$cmd_real_init" ]] ) ; then
				umount "$LOOP_ROOT"
				losetup -d /dev/loop0
				rmdir "$LOOP_ROOT"
				umount "$NEW_ROOT"
				rmdir "$NEW_ROOT"
				LOOP_ROOT=""
			fi
			if [[ "$LOOP_ROOT" != "$NEW_ROOT" ]] && [[ -n "${LOOP_ROOT##$NEW_ROOT/*}" ]] && [[ -e "$LOOP_ROOT" ]] && mount --move $NEW_ROOT $LOOP_ROOT/boot; then
				mount --move $LOOP_ROOT $NEW_ROOT
				rmdir $LOOP_ROOT && LOOP_ROOT="$NEW_ROOT"
			fi
		fi
		cp /proc/mounts /etc/mtab
		# around genkernel
		[[ -d "$NEW_ROOT" ]] && {
			REAL_ROOTFLAGS="$REAL_ROOTFLAGS,remount"
			if grep -q "^/dev/loop0 $NEW_ROOT " /proc/mounts; then
				LOOP=
				LOOPTYPE=
				REAL_ROOT=/dev/loop0
				REAL_ROOTFLAGS="loop,remount,ro"
			fi
		}
	fi
}

syspnp(){
	[[ -e "/lib/modules/${KV}/modules.alias.sh" ]] || return
	$cmd_nopnp && return
	# +some compats
	local PNP_TMP="${TMPDIR}/pnp.found" NOTLOADED="" CHK=single i i1 i2 gov="" freq="" pid="" LCOUNT="" REORDER=break USE_MDADM_="${USE_MDADM:=$cmd_domdadm}" USE_DMRAID_NORMAL_="${USE_DMRAID_NORMAL:=$cmd_dodmraid}" USE_EVMS_NORMAL_="${USE_EVMS_NORMAL:=$cmd_doevms}" USE_LVM_NORMAL_="${USE_LVM_NORMAL:=$cmd_dolvm}" LOOPS_="" REFRESH_SAME waitscan=true checks=""
	[[ "${USE_DMRAID_NORMAL:-true}" != true ]] && DMRAID_OPTS="$USE_DMRAID_NORMAL"
	: ${REAL_ROOT:=$cmd_real_root}
	: ${LOOP:=$cmd_loop}
	: ${LOOPTYPE:=$cmd_loop_type}
	: ${NFSROOT:=$cmd_nfsroot}
	for i in ${LOOPS:-"/*"}; do
		LOOPS_="${LOOPS_} /DETECT_ROOT$i"
	done
	[[ ${cmd_passwd:-false} != false ]] && [[ -n /etc/passwd ]] &&
		echo "$cmd_passwd" >/etc/passwd

	good_msg "Searching pnp"
	override_modprobe
	[[ "${SHLOADED##* modprobe }" == "${SHLOADED}" ]] && mod(){ modprobe -q -a "${@}";}
	loadsh blkid
	empty_hwopts firewire net pata pcmcia sata scsi usb   ataraid dmraid evms lvm mdadm fs
	[[ -z "$ISCSI_INITIATORNAME$ISCSI_TARGET$ISCSI_ADDRESS" ]] && empty_hwopts iscsi
    for pnpass in 0 0; do
	for i in 0 1 2 3 4 5; do
		echo -ne "" >"${PNP_TMP}.$i"
	done
	REORDER=break
	REFRESH_SAME=
	CHK=true
	etc_modalias
	refresh n
	load_hand_made0
	# first pass - strict bus order
	$cmd_fast && ofast_modalias || ordered_modalias $SYS_FIND
	CHK=single
	etc_modalias

#	refresh
	# paranoid
	while refresh && count ; do
		fast_modalias
	done

	REFRESH_SAME=1
	checks="$checks /proc/partitions"
	while count ; do
		if [[ -n "$REORDER" ]]; then
			REORDER=""
			load_hand_made
			wait $pid $pids
			pid=""
			pids=""
		else
			$cmd_fast || fast_modalias
		fi
		etc_modalias
		$cmd_unload && refresh
		load_misc
		etc_modalias && ln -s /proc /etc/modalias 2>/dev/null
		refresh n || break
	done
	[[ $pnpass != 1 ]] && break
	mntnewroot
	mount --bind $NEW_ROOT/lib/modules /lib/modules || break
	mount --bind $NEW_ROOT/lib/firmware /lib/firmware
	good_msg "Thin boot, pass 2"
    done

	MY_HWOPTS=""
	MDOLIST=""
	USE_MDADM="${USE_MDADM_}"
	USE_DMRAID_NORMAL="${USE_DMRAID_NORMAL_}"
	USE_LVM_NORMAL="${USE_LVM_NORMAL_}"
	USE_EVMS_NORMAL="${USE_EVMS_NORMAL_}"

#	echo -ne "\033[0G\033[0K"
	j=0
	for i in /sys/module/*; do
		let j=j+1
	done
	echo "$j modules"

	# assign detected root/loop
	if [[ -z "$REAL_ROOT" ]]; then
		DETECTED_ROOTS="${DETECTED_ROOTS# }"
		DETECTED_LOOPS="${DETECTED_LOOPS# }"
		[[ "${DETECTED_ROOTS#* }" == "$DETECTED_ROOTS" ]] && DETECTED_ROOT="$DETECTED_ROOTS"
		[[ "${DETECTED_LOOPS#* }" == "$DETECTED_LOOPS" ]] && DETECTED_LOOP="$DETECTED_LOOPS"
		[[ "${cmd_loop:-true}" == true ]] && REAL_ROOT="$DETECTED_ROOT"
		( [[ "$cmd_loop" != true ]] || [[ -z "$DETECTED_ROOTS" ]] ) && [[ -z "$REAL_ROOT" ]] && set_root_loop "$DETECTED_LOOP"
		if [[ -z "$REAL_ROOT" ]]; then
			[[ -n "$DETECTED_ROOTS" ]] && bad_msg "Detected possible root devices: $DETECTED_ROOTS"
			[[ -n "$DETECTED_LOOPS" ]] && bad_msg "Detected loopbacks: $DETECTED_LOOPS"
		fi
	fi

	# genkernel
	! ${1:-false} && [[ -n "$REAL_ROOT" ]] && [[ -n "$LOOP" ]] &&
		mntnewroot

	good_msg "Boot time: $(cat /proc/uptime)"
	if [[ -n "${NOTLOADED}" ]] ; then
		good_msg "Not loaded:$NOTLOADED"
		# try again
		MDOLIST="$NOTLOADED"
	fi
	rm "${PNP_TMP}".?
#	cd /
}

run_shell(){
	[[ -z "$SHELL" ]] && for SHELL in /bin/ash /bin/bash /bin/sh; do
		[[ -e "$SHELL" ]] && break
	done
	export SHELL
	if [[ -n "$cmd_vkb_touchscreen" ]] || grep "^B: ABS=........" /proc/bus/input/devices ; then
		vkb
	else
		$SHELL
	fi
}

# minimalistic. debug
if [[ -z "$KV"  ]] && ! [[ -e /proc/version ]]; then
NEW_ROOT="/newroot"
CDROOT=0
good_msg(){
echo "$*"
}
bad_msg(){
echo "! $*"
}
mount -t proc proc /proc
/bin/busybox --install -s
mount -t sysfs sys /sys
echo /sbin/mdev >/proc/sys/kernel/hotplug
cd /sys
if [[ -e /dev/null ]] || /sbin/mdev -s mem; then
	/sbin/mdev -s &
else
	/sbin/mdev -s
fi
#pids="$pids$! "
KV=`uname -r`
pnp_init
rm /sbin/modprobe 2>/dev/null
override_modprobe
syspnp true
cd /
while true; do
	[[ -n "$REAL_ROOT" ]] && mntnewroot
	if [[ -n "$LOOP_ROOT" ]] && [[ -d "$LOOP_ROOT" ]] &&
	    [[ "$LOOP_ROOT" != "$NEW_ROOT" ]]; then
		mkdir /rd 2>/dev/null
		( mnt_loop /dev/loop1 /lib.loopfs /rd && link_dir /rd /lib ) ||
		( mnt_loop /dev/loop1 /rd.loopfs /rd && link_dir /rd )
		link_dir "$LOOP_ROOT"
		mod_unload
		umount /proc /sys
		exec "$cmd_real_init" "$cmd_init_opts"
	elif [[ -d "$NEW_ROOT" ]]; then
		mod_unload
		umount /proc /sys
		exec /sbin/switch_root -c /dev/console "$NEW_ROOT" "$cmd_real_init" "$cmd_init_opts"
	else
		bad_msg "failed to mount root"
		while true; do
			cat /lib/keymaps/keymapList 2>/dev/null
			echo -n "Enter root partition, keymap or 'shell':"
			REAL_ROOT=`SHELL="" vkb`
			loadkmap <"/lib/keymaps/$REAL_ROOT.map" 2>/dev/null || break
		done
		set_root_loop "$REAL_ROOT"
		[[ "$REAL_ROOT" == shell ]] || continue
	fi
	bad_msg "failed to switch root"
	run_shell
done
fi
